<?php
/**
 * 中钢银通支付
 */

namespace app\api\service\payment;


use app\api\service\ApiPayment;
use app\common\library\exception\OrderException;
use think\Log;

class Gpay extends ApiPayment
{
    public function unionpay($order)
    {
        return $this->requestApi($order);
    }

    public function requestApi($order)
    {
        $rand = md5(time() . mt_rand(0, 1000)); //随机生成32位字符串
        $time = date('YmdHis', time()); //获取当前系统时间
        $out_trade_no = $time . rand(1000, 9999); //生成订单编号

        //支付请求报文
        $sourData  = array(
            'nonce_str'     => $rand, //随机32位字符串 Y
            'payment_type'  => 'pay-yl-native', //支付方式代码 Y
            'out_trade_no'  => $order['out_trade_no'], //商户订单号 Y
            'time_start'    => $time, //订单生成时间 Y
            'total_fee'     => bcmul($order['amount'], 100), //订单金额，单位到分 需要*100后传输，如0.01元订单传值为：1 Y
            'fee_type'      => 'CNY', //币种，默认传值：CN Y
            'body'          => 'test', //商品描述 Y
            'notify_url'    => 'http://111.231.76.48/notify/gpay', //付款成功后的异步回调地址 Y
            'mch_create_ip' => '127.0.0.1' //订单提交终端IP
        );

        $sourData = json_encode($sourData);


        $encryptType = 'NONE';
        $merchantNo  = $this->config['app_id'];
        $key = $this->config['app_key'];
        $requestId   = intval(microtime(true));
        $requestTime = $time;
        $serviceName = 'submit.order';
        $signType    = 'MD5';
        $sourceData  = $sourData;
        $version = '2.0';

        $signSource = "encryptType={$encryptType}&merchantNo={$merchantNo}&requestId={$requestId}&requestTime=$time&serviceName=submit.order&signType={$signType}&sourceData=$sourData&version={$version}&key={$key}";
        $signData        =  md5($signSource);




        $data['encryptType'] = $encryptType;
        $data['merchantNo']  = $merchantNo;
        $data['requestId']   = $requestId;
        $data['requestTime'] = $requestTime;
        $data['serviceName'] = $serviceName;
        $data['signData']    = $signData;
        $data['signType']    = $signType;
        $data['sourceData']  = $sourceData;
        $data['version']     = $version;
        $url                 = 'https://jh.g-pay.cn/api/order.do';
        $result              =  self::curl($url, json_encode($data)); // 发起远程请求

        $return_code = json_decode($result);
        $res = $return_code->sourceData;
        $res_array = (array)json_decode($res);
        $result_code = $res_array['result_code']; //返回值0成功 -1失败
        if ($result_code == 0) {
            //   $code_img_url = $res_array['code_img_url'];//支付二维码链接
            //   var_dump("<br>成功，二维码链接：".$code_img_url."<br><br><br><br>");//打印二维码链接

            return [
                'order_id' => $order['out_trade_no'],
                'pay_seq' => $order['trade_no'],
                'pay_url' => $res_array['code_img_url'],
            ];
        } else {
            return false;
            //   $err_code_des = $res_array['err_code_des'];//失败原因
            //   var_dump("<br>失败，失败的原因：".$err_code_des."<br><br><br><br>");//打印失败原因
        }
    }

    public static function curl($url, $data)
    {
        header("Content-type: text/html; charset=utf-8");
        $curl = curl_init();
        //设置抓取的url
        curl_setopt($curl, CURLOPT_URL, $url);
        //设置获取的信息以文件流的形式返回，而不是直接输出。
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        //设置头文件的信息作为数据流输出
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);
        // 告诉curl禁用ssl当中的公用名,公用名只有两种值0表没有，1表示拥有，默认为1
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        //设置post方式提交
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        //为没有ssl所有不要进行认证的校验
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt(
            $curl,
            CURLOPT_HTTPHEADER,
            array(
                'Content-Type: application/json; charset=utf-8',
                'Content-Length: ' . strlen($data)
            )
        );
        json_encode($data, JSON_UNESCAPED_UNICODE); //解决json处理传送中文问题
        //执行命令
        $str = curl_exec($curl);
        //关闭URL请求
        curl_close($curl);
        //把请求的数据进行返回
        return $str;
    }

    /**
     * 签名
     *
     * @param $param
     * @param $key
     *
     * @return string
     */
    private function buildRequestSign($param, $key)
    {
        return md5(self::getSignContent($param) . $key);
    }

    public function notify()
    {
        return $this->verifyOrderNotify();
    }

    /**
     * 回调验签
     *
     *
     * @return array
     * @throws OrderException
     */
    private function verifyOrderNotify()
    {
        $sourceData = \think\Request::instance()->param('sourceData');

        Log::write("Gpay notify Request:\n\nsourceData: $sourceData");
        $sourceDataArr = json_decode($sourceData, true);
        if ($sourceDataArr['result_code'] != '0' || $sourceDataArr['pay_status'] != 'SUCCESS') {
            return false;
        }

        $order = [
            'out_trade_no' => $sourceDataArr['out_trade_no'],
        ];

        return $order;

        libxml_disable_entity_loader(true);
        //Object  对象
        $response = json_decode(json_encode(simplexml_load_string(file_get_contents("php://input"), 'SimpleXMLElement', LIBXML_NOCDATA), JSON_UNESCAPED_UNICODE), true);
        //读订单对应的支付渠道配置
        $this->config = self::getOrderPayConfig($response['out_trade_no']);
        if (self::getWxpaySign($response, $this->config['mch_key']) !== $response['sign']) {
            Log::error('Verify WxOrder Notify Error');
            throw new OrderException([
                'msg'   => 'Verify WxOrder Notify Error',
                'errCode'   => 200010
            ]);
        }
        echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
    }

    /**
     * 数据排序
     *
     * @param $data
     *
     * @return string
     */
    private function getSignContent($data)
    {
        ksort($data);

        $stringToBeSigned = '';

        foreach ($data as $k => $v) {
            if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {

                if ($v !== '' && !is_null($v) && $k != 'sign' && '@' != substr($v, 0, 1)) {
                    $stringToBeSigned .= $k . '=' . $v . '&';
                }
            }
        }
        Log::notice('Hnpay API Sign Content:' . $stringToBeSigned);
        return $stringToBeSigned;
    }

    /**
     * 校验$value是否非空
     *
     *
     * @param $value
     *
     * @return bool
     */
    protected function checkEmpty($value)
    {
        if (!isset($value))
            return true;
        if ($value === null)
            return true;
        if (trim($value) === "")
            return true;
        return false;
    }
}
